
.text
.global main 
        .global writeint
        ## void writeint(int n)
        ## writes n on sysout
	
        .global readint
        ## int readint()
        ## reads an integer from sysin
        ## return value is in eax
	
        .global writestr
        ## void writestr(char[] str, int n)
        ## writes n characters from str on sysout
	
        .global writeln
        ## void writeln()
        ## writes a newline character on sysout
	
        .global exit            
        ## void exit(int n)
        ## terminates execution with error code n
main:
                                                          
FUNCTION_start_printComplexNested:
                             
	PUSHL		%ebp		#save parent base pointer
	PUSHL		%ebx		#save parent var pointer
	PUSHL		%edi		#save parent temp pointer
	MOVL		%esp,		%ebp		#set new base pointer
	PUSHL		%esi		#backup current arg/par() pointer
	MOVL		%esp,		%ebx		#set new var pointer
	SUBL		$4,		%esp		#allocate vars
	MOVL		%esp,		%edi		#set new temp pointer
	SUBL		$8,		%esp		#allocate temps

	MOVL		$0,		%eax
	MOVL		%eax,		-4(%ebx)
                        
	MOVL		%esp,		%esi		#Set temporary args pointer
	SUBL		$0,		%esp		#Allocate args 

	CALL		FUNCTION_start_printComplexNested_p1
                    
	MOVL		%ecx,		%eax
	MOVL		%eax,		-4(%edi)
                      
	ADDL		$0,		%esp
	MOVL		-4(%ebp),		%esi		#restore current arg/par() pointer

	MOVL		%esp,		%esi		#Set temporary args pointer
	SUBL		$4,		%esp		#Allocate args 

	MOVL		-4(%ebx),		%eax
	MOVL		%eax,		-4(%esi)
                  
	CALL		writeint
                                                
	MOVL		%ecx,		%eax
	MOVL		%eax,		-8(%edi)
                      
	ADDL		$1,		%esp
	MOVL		-4(%ebp),		%esi		#restore current arg/par() pointer

	MOVL		%ebp,		%esp
	POPL		%edi		#restore parent temp() pointer
	POPL		%ebx		#restore parent var() pointer
	POPL		%ebp		#restore parent base pointer
RET

FUNCTION_start_printComplexNested_p1:
                          
	PUSHL		%ebp		#save parent base pointer
	PUSHL		%ebx		#save parent var pointer
	PUSHL		%edi		#save parent temp pointer
	MOVL		%esp,		%ebp		#set new base pointer
	PUSHL		%esi		#backup current arg/par() pointer
	MOVL		%esp,		%ebx		#set new var pointer
	SUBL		$4,		%esp		#allocate vars
	MOVL		%esp,		%edi		#set new temp pointer
	SUBL		$16,		%esp		#allocate temps

	MOVL		$2,		%eax
	MOVL		%eax,		-4(%ebx)
                        
	MOVL		%ebp,		%eax		#start with ebp pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%ebx),		%eax		#store address to destination address
	POPL		%ebx		#Restore current pointer
	ADDL		-4(%ebx),		%eax		#store address to destination address
	MOVL		%eax,		-4(%edi)		#store address to destination address

	MOVL		%ebp,		%eax		#start with ebp pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%edi),		%eax
	MOVL		%eax,		-4(%ebx)
	POPL		%ebx		#Restore current pointer

	MOVL		%esp,		%esi		#Set temporary args pointer
	SUBL		$4,		%esp		#Allocate args 

	MOVL		%ebp,		%eax		#start with ebp pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%ebx),		%eax
	POPL		%ebx		#Restore current pointer
	MOVL		%eax,		-4(%esi)

	CALL		writeint
                                                
	MOVL		%ecx,		%eax
	MOVL		%eax,		-8(%edi)
                      
	ADDL		$1,		%esp
	MOVL		-4(%ebp),		%esi		#restore current arg/par() pointer

IF_3_10:
                                                       
	MOVL		%ebp,		%eax		#start with ebp pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%ebx),		%eax		#store address to destination address
	POPL		%ebx		#Restore current pointer
	CMP		-4(%ebx),		%eax		#store address to destination address

	JNE		else_IF_3_10		#conditional jump
                          
	MOVL		%esp,		%esi		#Set temporary args pointer
	SUBL		$0,		%esp		#Allocate args 

	CALL		FUNCTION_start_printComplexNested_p1_p2
                 
	MOVL		%ecx,		%eax
	MOVL		%eax,		-16(%edi)
                     
	ADDL		$0,		%esp
	MOVL		-4(%ebp),		%esi		#restore current arg/par() pointer

	JMP		break_IF_3_10
                                            
else_IF_3_10:
                                                  
break_IF_3_10:
                                                 
	MOVL		%ebp,		%esp
	POPL		%edi		#restore parent temp() pointer
	POPL		%ebx		#restore parent var() pointer
	POPL		%ebp		#restore parent base pointer
RET

FUNCTION_start_printComplexNested_p1_p2:
                       
	PUSHL		%ebp		#save parent base pointer
	PUSHL		%ebx		#save parent var pointer
	PUSHL		%edi		#save parent temp pointer
	MOVL		%esp,		%ebp		#set new base pointer
	PUSHL		%esi		#backup current arg/par() pointer
	MOVL		%esp,		%ebx		#set new var pointer
	SUBL		$0,		%esp		#allocate vars
	MOVL		%esp,		%edi		#set new temp pointer
	SUBL		$8,		%esp		#allocate temps

	MOVL		%ebp,		%eax		#start with ebp pointer
	MOVL		8(%eax),		%eax		#becomes parent pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%ebx),		%eax		#store address to destination address
	POPL		%ebx		#Restore current pointer
	ADDL		$1,		%eax		#store address to destination address
	MOVL		%eax,		-4(%edi)		#store address to destination address

	MOVL		%ebp,		%eax		#start with ebp pointer
	MOVL		8(%eax),		%eax		#becomes parent pointer
	PUSHL		%ebx		#back up current pointer
	MOVL		4(%eax),		%ebx		#extract pointer value to pointer register
	MOVL		-4(%edi),		%eax
	MOVL		%eax,		-4(%ebx)
	POPL		%ebx		#Restore current pointer

	MOVL		%esp,		%esi		#Set temporary args pointer
	SUBL		$0,		%esp		#Allocate args 

	CALL		FUNCTION_start_printComplexNested_p1
                    
	MOVL		%ecx,		%eax
	MOVL		%eax,		-8(%edi)
                      
	ADDL		$0,		%esp
	MOVL		-4(%ebp),		%esi		#restore current arg/par() pointer

	MOVL		%ebp,		%esp
	POPL		%edi		#restore parent temp() pointer
	POPL		%ebx		#restore parent var() pointer
	POPL		%ebp		#restore parent base pointer
RET



writeint:
         pushl   %ebp            # save old base pointer
         pushl   %ebx            # save ebx
         pushl   %edi            # save edi
         movl    %esp, %ebp      # set base pointer
         movl    16(%ebp), %eax  # copy argument to eax 
         movl    $10, %ecx       # set divisor to 10
         subl    $12, %esp       # allocate for local string
         movl    %ebp, %edi      # set edi 
         cmpl    $0, %eax        # argument negative?
         jge     writedigit
         negl    %eax            # negate
writedigit:  
         movl    $0, %edx        # set up for 64 bit division
         idivl   %ecx            # divide edx:aex by 10
         addl    $'0, %edx       # ascii digit in edx
         decl    %edi            # push ...
         movb    %dl, (%edi)     # digit 
         cmpl    $0, %eax        # quotient=0 ?
         jg      writedigit
         cmpl    $0, 16(%ebp)    # argument negative?
         jge     nosign
         decl    %edi            # push ...
         movb    $'-, (%edi)     # '-'
nosign:  movl    %ebp, %edx
         subl    %edi, %edx      # third argument: string length
         movl    %edi, %ecx      # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         movl    %ebp, %esp      # restore stack pointer
         popl    %edi            # restore edi
         popl    %ebx            # restore ebx
         popl    %ebp            # restore base pointer
         ret                     # return
         
readint:
         pushl   %ebp            # save old base pointer
         pushl   %ebx            # save ebx
         pushl   %edi            # save edi
         movl    %esp, %ebp      # set base pointer
         subl    $12, %esp       # allocate memory
         movl    %esp, %edi
         movl    $12, %edx       # maximal string length
         movl    %edi, %ecx      # string address
         movl    $0, %ebx        # file descriptor
         movl    $3, %eax        # sys_read interrupt index
         int     $0x80           # kernel interrupt sys_read 
         addl    %eax, %ecx      # address of ...
         decl    %ecx            # last character
         # parse input
         movl    $0, %eax        # result accumulator
         cmpb    $'-, -12(%ebp)  # negative number?
         jne     readdigit
         incl    %edi            # skip '-'
readdigit:
         imull   $10, %eax       # multiply result by 10
         movl    $0, %edx        # copy digit ...
         movb    (%edi), %dl     # to dl
         subl    $'0, %edx       # convert ascii to value
         addl    %edx, %eax      # add value to result
         incl    %edi            # address of next digit
         cmpl    %edi, %ecx      # end of string?
         jg      readdigit
         cmpb    $'-, -12(%ebp)  # negative number?
         jne     rest
         negl    %eax            # negate result
rest:    movl    %ebp, %esp      # restore stack pointer
         popl    %edi            # restore edi
         popl    %ebx            # restore ebx
         popl    %ebp            # restore base pointer
         ret
         
writestr:
         pushl   %ebx            # save ebx
         movl    12(%esp), %edx  # third argument: string length
         movl    8(%esp), %ecx   # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         popl    %ebx            # restore ebx
         ret                     # return

writeln:
         pushl   %ebx            # save ebx
         pushl   $10             # push newline character
         movl    $1, %edx        # third argument: string length
         movl    %esp, %ecx    # second argument: string address
         movl    $1, %ebx        # first argument: file descriptor
         movl    $4, %eax        # sys_write interrupt index
         int     $0x80           # kernel interrupt sys_write
         addl    $4, %esp        # pop stack
         popl    %ebx            # restore ebx
         ret                     # return
         
exit:
         movl    4(%esp), %ebx   # first argument: error code 
         movl    $1, %eax        # sys_exit interrupt index
         int     $0x80           # kernel interrupt sys_exit
